package com.ctshk.rpc.order.train.service.impl;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONException;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.ctshk.common.constant.CurrencyRateExchangeConstant;
import com.ctshk.common.dto.Result;
import com.ctshk.common.enums.Currency;
import com.ctshk.common.enums.*;
import com.ctshk.common.enums.bus.BusConst;
import com.ctshk.common.exception.BusinessException;
import com.ctshk.common.mail.core.MailTemplate;
import com.ctshk.common.model.PageResponse;
import com.ctshk.common.model.TokenUser;
import com.ctshk.common.service.support.BaseService;
import com.ctshk.common.sms.core.SmsUtil;
import com.ctshk.common.utils.*;
import com.ctshk.common.vo.OrderRefundDTO;
import com.ctshk.rpc.booking.enums.SupplierReserveTypeEnum;
import com.ctshk.rpc.booking.req.system.SupplierOrderSystemFreeCallConfirmReq;
import com.ctshk.rpc.booking.req.system.train.add.SupplierOrderSystemTrainAddReq;
import com.ctshk.rpc.booking.req.system.train.add.SupplierSystemOrderTrainAddReq;
import com.ctshk.rpc.booking.req.system.train.add.SupplierSystemOrderTrainTicketAddReq;
import com.ctshk.rpc.booking.service.ISupplierOrderService;
import com.ctshk.rpc.finance.json.AccountJson;
import com.ctshk.rpc.finance.json.FileJson;
import com.ctshk.rpc.finance.req.bill.BillAddCollectionReq;
import com.ctshk.rpc.finance.req.bill.BillAddRefundReq;
import com.ctshk.rpc.finance.req.onaccount.UseQuotaReq;
import com.ctshk.rpc.finance.service.IFinanceBillService;
import com.ctshk.rpc.finance.service.IFinanceOnAccountCurrencyQuotaService;
import com.ctshk.rpc.insurance.service.IInsuranceService;
import com.ctshk.rpc.iotc.dto.OperateBankPreferenceQueryDTO;
import com.ctshk.rpc.iotc.req.OperateBankConformQueryReq;
import com.ctshk.rpc.iotc.service.IOperateBankPreferenceService;
import com.ctshk.rpc.order.train.dto.*;
import com.ctshk.rpc.order.train.entity.*;
import com.ctshk.rpc.order.train.enums.ActionEnum;
import com.ctshk.rpc.order.train.manager.TrainOrderManager;
import com.ctshk.rpc.order.train.mapper.*;
import com.ctshk.rpc.order.train.req.*;
import com.ctshk.rpc.order.train.service.ITrainOrderService;
import com.ctshk.rpc.system.dto.MainDataCurrencyListDTO;
import com.ctshk.rpc.system.dto.MainDataCurrencyQueryDTO;
import com.ctshk.rpc.system.dto.SysDepartmentDTO;
import com.ctshk.rpc.system.dto.UserDTO;
import com.ctshk.rpc.system.dto.member.ContactQueryDTO;
import com.ctshk.rpc.system.req.MainDataCurrencyListReq;
import com.ctshk.rpc.system.req.MainDataCurrencyUpdateStatusReq;
import com.ctshk.rpc.system.req.crm.member.CrmMemberQueryReq;
import com.ctshk.rpc.system.service.*;
import com.ctshk.rpc.train.dto.TrainPriceRemainderDTO;
import com.ctshk.rpc.train.dto.TrainProductCostPriceDTO;
import com.ctshk.rpc.train.dto.TrainProductDTO;
import com.ctshk.rpc.train.dto.TrainProductReservationSettingsDTO;
import com.ctshk.rpc.train.service.ITrainProductCostService;
import com.ctshk.rpc.train.service.ITrainProductService;
import com.ctshk.rpc.workflow.dto.ApprovalCheckDTO;
import com.ctshk.rpc.workflow.dto.ApprovalStartDTO;
import com.ctshk.rpc.workflow.service.ISysApprovalService;
import com.google.common.collect.Lists;
import org.apache.commons.lang3.StringUtils;
import org.apache.dubbo.config.annotation.DubboReference;
import org.apache.dubbo.config.annotation.DubboService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

import java.math.BigDecimal;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.Period;
import java.util.*;
import java.util.function.Function;
import java.util.stream.Collectors;

/**
 * <p>
 * 火车票订单表 服务实现类
 * </p>
 *
 * @author 彭柳霖
 * @since 2021-03-17
 */
@DubboService
public class TrainOrderServiceImpl extends ServiceImpl<TrainOrderMapper, TrainOrder> implements ITrainOrderService, BaseService {

    @Autowired
    private TrainOrderTouristMapper trainOrderTouristMapper;

    @Autowired
    private TrainOrderCollectionMapper trainOrderCollectionMapper;

    @Autowired
    private TrainOrderRefundMapper trainOrderRefundMapper;

    @Autowired
    private TrainManualOrderMapper trainManualOrderMapper;

    @Autowired
    private TrainOrderMapper trainOrderMapper;

    @DubboReference
    private ITrainProductService trainProductService;

    @DubboReference
    private ITrainProductCostService trainProductCostService;

    @DubboReference
    ICrmMemberService crmMemberService;

    @DubboReference
    private IMainDataCurrencyService iMainDataCurrencyService;

    @DubboReference
    ISysDepartmentService sysDepartmentService;

    @DubboReference
    ISysUserService sysUserService;

    @DubboReference
    IOperateBankPreferenceService operateBankPreferenceService;

    @DubboReference
    ISupplierOrderService supplierOrderService;

    @DubboReference
    private ISysUserService iSysUserService;

    @DubboReference
    private IFinanceBillService iFinanceBillService;

    @DubboReference
    IMainDataCurrencyService mainDataCurrencyService;

    @DubboReference
    ISysApprovalService sysApprovalService;

    @Autowired
    private MailTemplate mailTemplate;

    @DubboReference
    private IInsuranceService iInsuranceService;

    @DubboReference
    private IFinanceOnAccountCurrencyQuotaService onAccountCurrencyQuotaService;
    @DubboReference
    private ISysPermissionService sysPermissionService;

    @Override
    public ActionEnum getActionType() {
        return ActionEnum.DEFAULT;
    }

    /**
     * 填写订单信息
     *
     * @param trainPlaceOrderReq
     * @param user
     * @return
     */
    @Transactional(rollbackFor = Exception.class)
    @Override
    public Result addOrder(TrainPlaceOrderReq trainPlaceOrderReq, TokenUser user) {
        LocalDate nowLocalDate = LocalDate.now();
        List<TrainOrderTourist> busOrderTouristList = EntityUtil.copyList(trainPlaceOrderReq.getTrainOrderTouristReqList(), TrainOrderTourist.class);
        int adultNumber = 0;
        int childrenNumber = 0;

        // 保险总额
        BigDecimal insurancePriceTotal = BigDecimal.ZERO;
        for (TrainOrderTourist tourist : busOrderTouristList) {
            String touristType = tourist.getTouristType();
            if("1".equals(touristType)) {
                adultNumber++;
            } else if ("2".equals(touristType)) {
                childrenNumber++;
            }

            //计算年龄
            Period dateBetween = Period.between(tourist.getBirthday(), nowLocalDate);

            insurancePriceTotal = tourist.getInsurancePrice() == null?BigDecimal.ZERO:tourist.getInsurancePrice();
        }
        /*StringBuffer sb = new StringBuffer();
        if(adultNumber != actualAdultNumber) {
            sb.append("成人个数不符,请检查生日。");
        }
        if(childrenNumber != actualChildrenNumber) {
            sb.append("小童个数不符,请检查生日。");
        }
        String tips = sb.toString();
        if(StringUtils.isNotBlank(tips)) {
            return Result.failed(new BusinessException(SystemError.TRAIN_ORDER_24000,tips));
        }*/
        // 获取火车产品相关信息
        TrainProductDTO trainProductDTO = trainProductService.queryDetail(trainPlaceOrderReq.getTrainProductId());

        if(trainProductDTO == null) {
            throw new BusinessException(SystemError.TRAIN_PRODUCT_14004);
        }
        //获取预定设置
        TrainProductReservationSettingsDTO trainProductReservationSettingsDTO = trainProductDTO.getTrainProductReservationSettingsDTO();
        LocalDateTime nowLocalDateTime = LocalDateTime.now();

        int touristNumber = trainPlaceOrderReq.getTrainOrderTouristReqList().size();
        TrainPriceRemainderDTO trainPriceRemainderDTO;

        // 预定日期
        LocalDate effectiveDate = trainPlaceOrderReq.getEffectiveDate();
        // 查询加幅后的价格，售卖类型，余票
        if (trainPlaceOrderReq.getIsAgent() == 1) {
            trainPriceRemainderDTO = trainProductService.selectAgentPriceRemainderAndLock(trainPlaceOrderReq.getTrainProductId(), touristNumber, trainPlaceOrderReq.getAgencyId(), user.getId(),effectiveDate);
        } else {
            trainPriceRemainderDTO = trainProductService.selectSelfPriceRemainderAndLock(trainPlaceOrderReq.getTrainProductId(), touristNumber, user.getId(),effectiveDate);
        }

        TrainOrder trainOrder = EntityUtil.copy(trainPlaceOrderReq, TrainOrder.class);

        // 将火车产品相关数据设置到火车订单中
        trainOrder.setRailwayCorporationId(trainProductDTO.getRailwayCorporationId());
        trainOrder.setRailwayCorporationName(trainProductDTO.getRailwayCorporationName());
        trainOrder.setTrainNumberId(trainProductDTO.getTrainNumberId());
        trainOrder.setTrainNumberName(trainProductDTO.getTrainNumberName());
        trainOrder.setDepartureCityId(trainProductDTO.getDepartureCityId());
        trainOrder.setDepartureCityName(trainProductDTO.getDepartureCityName());
        trainOrder.setArriveCityId(trainProductDTO.getArriveCityId());
        trainOrder.setArriveCityName(trainProductDTO.getArriveCityName());
        trainOrder.setBoardingStationId(trainProductDTO.getBoardingStationId());
        trainOrder.setBoardingStationName(trainProductDTO.getBoardingStationName());
        trainOrder.setAlightingStationId(trainProductDTO.getAlightingStationId());
        trainOrder.setAlightingStationName(trainProductDTO.getAlightingStationName());
        trainOrder.setSeatLevelId(trainProductDTO.getSeatLevelId());
        trainOrder.setSeatLevelName(trainProductDTO.getSeatLevelName());
        trainOrder.setEffectiveTime(trainProductDTO.getDepartureTime());
        // 设置产品来源
        trainOrder.setProductType(trainProductDTO.getProductSource());
        // 设置出发日期时间
        // 获取火车产品的出发时间加上预定的日期
        LocalDateTime departureTime = trainProductDTO.getDepartureTime();
        trainOrder.setDepartureTime(LocalDateTime.of(effectiveDate, departureTime.toLocalTime()));
        if (trainOrder.getIsAgent() == 1) {
            trainOrder.setSource(OrderSource.CPM_PROXY.getCode());
        } else {
            trainOrder.setSource(OrderSource.CPM.getCode());
        }
        // 成人服务价格
        BigDecimal adultServiceChargePrice = BigDecimal.ZERO;
        // 小童服务价格
        BigDecimal childrenServiceChargePrice = BigDecimal.ZERO;
        // 预定设置不为空，取服务费
        if(trainProductReservationSettingsDTO != null) {
            // 计算服务费
            Integer serviceChargeType = trainProductReservationSettingsDTO.getServiceChargeType();
            BigDecimal serviceChargePrice = trainProductReservationSettingsDTO.getServiceChargePrice() == null?BigDecimal.ZERO:trainProductReservationSettingsDTO.getServiceChargePrice();
            if(serviceChargeType == 2) {
                // 百分比
                BigDecimal per = serviceChargePrice.divide(new BigDecimal("100"));
                BigDecimal adultPrimePrice = trainPriceRemainderDTO.getAdultPrimePrice() == null?BigDecimal.ZERO:trainPriceRemainderDTO.getAdultPrimePrice();
                BigDecimal childrenPrimePrice = trainPriceRemainderDTO.getChildrenPrimePrice() == null?BigDecimal.ZERO:trainPriceRemainderDTO.getChildrenPrimePrice();
                adultServiceChargePrice = adultPrimePrice.multiply(per);
                childrenServiceChargePrice = childrenPrimePrice.multiply(per);
            } else if(serviceChargeType == 1) {
                // 加数值
                adultServiceChargePrice = serviceChargePrice;
                childrenServiceChargePrice = serviceChargePrice;
            }
        }


        //计算总价
        BigDecimal adultPriceTotal = trainPriceRemainderDTO.getAdultPrice().add(adultServiceChargePrice).multiply(new BigDecimal(Integer.toString(adultNumber)));
        BigDecimal childrenPriceTotal = trainPriceRemainderDTO.getChildrenPrice().add(childrenServiceChargePrice).multiply(new BigDecimal(Integer.toString(childrenNumber)));
        BigDecimal orderAmount = adultPriceTotal.add(childrenPriceTotal).add(insurancePriceTotal);
        // 计算应收金额
        buildReceivableAmount(trainOrder, orderAmount);
        //获取火车订单编号
        trainOrder.setOrderNumber(buildOrderNumber(user.getId(), nowLocalDateTime));
        // 计算付款到期时间,+30分钟
        trainOrder.setPayExpireDate(nowLocalDateTime.plusMinutes(30));
        Long id = SnowflakeIdWorker.nextId();
        trainOrder.setId(id);
        trainOrder.setTrainId(trainPlaceOrderReq.getTrainProductId());
        trainOrder.setOrderAmount(orderAmount);
        trainOrder.setNumber(touristNumber);
        trainOrder.setContactName(trainOrder.getSurname() + trainOrder.getName());
        if(trainProductReservationSettingsDTO != null && trainProductReservationSettingsDTO.getIsConfirm() == 1) {
            // 立即确认
            trainOrder.setScheduledStatus(OrderScheduledStatus.CONFIRM_RESERVE.getCode());
        } else {
            // 二次确认，预定状态为待确认
            trainOrder.setScheduledStatus(OrderScheduledStatus.CONFIRM_RESERVE.getCode());
        }
        trainOrder.setScheduledStatus(0); //初始预定状态
        trainOrder.setPaymentStatus(OrderPaymentStatus.UN_PAYMENT.getCode()); //待付款
        trainOrder.setCancelStatus(0); //初始未取消
        trainOrder.setSalesmanId(user.getId());
        trainOrder.setSalesmanName(user.getUsername());
        trainOrder.setSalesMethods(1);//销售方式(1：单品销售 2：打包销售)
        trainOrder.setIsDeleted(IsDeletedCode.NO.getCode());
        trainOrder.setCreateId(user.getId());
        trainOrder.setGmtCreate(nowLocalDateTime);
        trainOrder.setOrderType(0);
        this.baseMapper.insert(trainOrder);

        BigDecimal finalAdultServiceChargePrice = adultServiceChargePrice;
        BigDecimal finalChildrenServiceChargePrice = childrenServiceChargePrice;
        busOrderTouristList.forEach(tourist -> {
            tourist.setId(SnowflakeIdWorker.nextId());
            tourist.setOrderId(id);
            // 成人
            if("1".equals(tourist.getTouristType())) {
                BigDecimal adultPrice = trainPriceRemainderDTO.getAdultPrice();
                tourist.setTicketPrice(adultPrice);
                tourist.setServiceChargePrice(finalAdultServiceChargePrice);
            } else if("2".equals(tourist.getTouristType())) {
                tourist.setServiceChargePrice(finalChildrenServiceChargePrice);
                tourist.setTicketPrice(trainPriceRemainderDTO.getChildrenPrice());
            }
            trainOrderTouristMapper.insert(tourist);
        });

        return Result.success(id);
    }

    /**
     * 支付页面查询信息
     *
     * @param id
     * @return
     */
    @Override
    public Result<TrainOrderPayInfoDTO> paymentInfoById(Long id) {
        TrainOrder trainOrder = baseMapper.selectById(id);
        TrainOrderPayInfoDTO trainOrderPayInfoDTO = EntityUtil.copy(trainOrder, TrainOrderPayInfoDTO.class);
        return Result.success(trainOrderPayInfoDTO);
    }

    /**
     * 预定中心下单
     *
     * @param reqList 预定中心订单入参
     * @return 返回值
     */
    @Transactional(rollbackFor = Exception.class)
    @Override
    public Result payOrder(Long id, List<TrainPayOrderCollectionReq> reqList, TokenUser user) {
        LocalDateTime nowLocalDateTime = LocalDateTime.now();
        TrainOrder trainOrder = baseMapper.selectById(id);
        if (Objects.isNull(trainOrder)) {
            return Result.failed(SystemError.SYS_411);
        }
        TrainProductDTO trainProductDTO = trainProductService.queryDetail(trainOrder.getTrainId());
        if (Objects.isNull(trainProductDTO)) {
            return Result.failed(SystemError.TRAIN_PRODUCT_14004);
        }
        if (nowLocalDateTime.isAfter(trainOrder.getPayExpireDate())) {
            // 支付超时
            throw new BusinessException(SystemError.TRAIN_PRODUCT_14018);
        }
        trainOrder.setPaymentStatus(OrderPaymentStatus.UN_PAYMENT.getCode());
        trainOrder.setModifiedId(user.getId());
        trainOrder.setGmtModified(nowLocalDateTime);
        // 计算支付总金额
        BigDecimal amountCountHKD = BigDecimal.ZERO;
        BigDecimal readyMoney = BigDecimal.ZERO;
        List<TrainOrderCollection> trainOrderCollectionList = EntityUtil.copyList(reqList, TrainOrderCollection.class);

        for (TrainOrderCollection trainOrderCollection : trainOrderCollectionList) {
            // 获取对应汇率，计算支付金额
            BigDecimal crmExchangeRate = getExchangeRateById(trainOrderCollection.getCurrencyId()).getCrmExchangeRate();
            BigDecimal amountHKD;
            if (trainOrderCollection.getIsUnionpayDiscount() == 1) {
                //银联优惠，do something银行优惠校验接口待完善
                amountHKD = getAmountByBankReference(trainOrder, trainOrderCollection.getUnionpayDiscountId());
            } else if (trainOrderCollection.getCollectionWayId() == 1 || trainOrderCollection.getCollectionWayId() == 2) {
                //统计实收金额，用于CRM会员积分,1-现金、2-信用卡金额
                amountHKD = trainOrderCollection.getCollectionAmount().multiply(crmExchangeRate);
                readyMoney = readyMoney.add(amountHKD);
            } else {
                amountHKD = trainOrderCollection.getCollectionAmount().multiply(crmExchangeRate);
            }
            amountCountHKD = amountCountHKD.add(amountHKD);
            trainOrderCollection.setOrderId(id);
            trainOrderCollection.setStatus(OrderCollectionStatus.UN_REJECT.getCode());
            trainOrderCollection.setId(SnowflakeIdWorker.nextId());
            trainOrderCollection.setSalerId(user.getId());
            trainOrderCollection.setSalerName(user.getUsername());
            trainOrderCollection.setIsDeleted(IsDeletedCode.NO.getCode());
            trainOrderCollection.setCreateId(user.getId());
            trainOrderCollection.setGmtCreate(nowLocalDateTime);


            // 设置收款单号
            trainOrderCollection.setCollectionNumber(TrainOrderManager.getCollectionNumber());
            trainOrderCollectionMapper.insert(trainOrderCollection);
        }
        // 校验应收价格
        if (amountCountHKD.compareTo(trainOrder.getReceivableAmount()) < 0) {
            // 支付价格小于应收价格
            throw new BusinessException(SystemError.TRAIN_PRODUCT_14019);
        }

        // 通知财务 获取当前用户信息
        UserDTO userDTO = iSysUserService.getUser(new UserDTO().setUsername(user.getUsername()));
        if (null == userDTO) {
            return Result.failed(SystemError.USER_1002);
        }
        addCollection(trainOrder, userDTO, trainOrderCollectionList, trainProductDTO, user);
        // 通知财务成功修改支付状态为已付款
        TrainOrder updatePaymentStatusTrainOrder = new TrainOrder();
        updatePaymentStatusTrainOrder.setId(trainOrder.getId());
        // 默认已付款后预订状态为确认预订,外挂单和代理商下单需要根据产品中的预订设置是否需要二次确认
        if(trainOrder.getOrderType() == 1 || OrderSource.CPM_PROXY.getCode().equals(trainOrder.getSource())) {
            //获取预订设置
            TrainProductReservationSettingsDTO trainProductReservationSettingsDTO = trainProductDTO.getTrainProductReservationSettingsDTO();
            if(trainProductReservationSettingsDTO != null) {
                // 是否二次确认
                Integer isConfirm = trainProductReservationSettingsDTO.getIsConfirm();
                if(isConfirm == 1) {
                    updatePaymentStatusTrainOrder.setScheduledStatus(OrderScheduledStatus.CONFIRM_RESERVE.getCode());
                } else {
                    updatePaymentStatusTrainOrder.setScheduledStatus(OrderScheduledStatus.RESERVE_SUCCESS.getCode());
                }
            } else {
                updatePaymentStatusTrainOrder.setScheduledStatus(OrderScheduledStatus.RESERVE_SUCCESS.getCode());
            }
        } else {
            updatePaymentStatusTrainOrder.setScheduledStatus(OrderScheduledStatus.RESERVE_SUCCESS.getCode());
        }
        updatePaymentStatusTrainOrder.setPaymentStatus(OrderPaymentStatus.ALREADY_PAYMENT.getCode());
        updatePaymentStatusTrainOrder.setModifiedId(user.getId());
        updatePaymentStatusTrainOrder.setGmtModified(LocalDateTime.now());
        baseMapper.updateById(updatePaymentStatusTrainOrder);

        // 挂账 代理下单
        callFinanceOnAccount(trainOrder,user,trainProductDTO,trainOrderCollectionList, userDTO);

        // 生成供应商订单
        List<TrainOrderTourist> touristList = trainOrderTouristMapper.selectListByKey(TrainOrderTourist::getOrderId, trainOrder.getId());
        payOrderToSupplier(user, trainOrder, trainProductDTO, touristList, userDTO);
        return Result.success();
    }

    @Override
    public Result<QueryQuotaDTO> queryQuota(QueryQuotaReq req) {
        TrainOrder trainOrder = baseMapper.selectById(req.getOrderId());
        if (Objects.isNull(trainOrder)) {
            return Result.failed(SystemError.SYS_411);
        }
        com.ctshk.rpc.finance.req.onaccount.QueryQuotaReq queryQuotaReq = new com.ctshk.rpc.finance.req.onaccount.QueryQuotaReq();
        queryQuotaReq.setAccountId(trainOrder.getAgencyId());
        queryQuotaReq.setCurrencyId(req.getCurrencyId());
        Result<com.ctshk.rpc.finance.dto.onaccount.QueryQuotaDTO> queryQuotaDTOResult = onAccountCurrencyQuotaService.queryQuota(queryQuotaReq);
        if (queryQuotaDTOResult.getCode() != 0){
            throw new BusinessException(SystemError.LOCAL_FUN_18008, queryQuotaDTOResult.getMsg());
        }
        com.ctshk.rpc.finance.dto.onaccount.QueryQuotaDTO data = queryQuotaDTOResult.getData();
        QueryQuotaDTO queryQuotaDTO = EntityUtil.copy(data, QueryQuotaDTO.class);
        return Result.success(queryQuotaDTO);
    }

    /**
     * 代理下单 挂账
     */
    private void callFinanceOnAccount(TrainOrder trainOrder, TokenUser user, TrainProductDTO trainProductDTO, List<TrainOrderCollection> trainOrderCollectionList, UserDTO userDTO) {
        //代理下单
        if(trainOrder.getIsAgent() == 1){
            List<UseQuotaReq> useQuotaReqs = new ArrayList<>();
            for(TrainOrderCollection collectionReq : trainOrderCollectionList){
                //挂账
                UseQuotaReq useQuotaReq = new UseQuotaReq();
                if (PayRefundMethod.AC.getId().equals(collectionReq.getCollectionWayId())) {
                    useQuotaReq.setAccountType(1);

                    //代理 账号为代理下单公司的ID
                    if (BusConst.CLIENT_TYPE_AGENT.equals(trainOrder.getClientType())) {
                        useQuotaReq.setAccountId(trainOrder.getAgencyId());
                    } else if (BusConst.CLIENT_TYPE_BIG.equals(trainOrder.getClientType())) {  //大客户
                        useQuotaReq.setAccountId(trainOrder.getBigClientId());
                        useQuotaReq.setBigClientId(trainOrder.getBigClientId());
                        useQuotaReq.setBigClientName(trainOrder.getBigClientName());
                    }
                } else {
                    continue;
                }

                useQuotaReq.setDeptId(userDTO.getDeptId());
                useQuotaReq.setAccountId(trainOrder.getAgencyId());
                useQuotaReq.setAmount(collectionReq.getCollectionAmount());
                //收款单号
                useQuotaReq.setBillNumber(collectionReq.getCollectionNumber());
                useQuotaReq.setBusinessType(SystemBusinessType.TRAIN_TICKET.getCode());
                useQuotaReq.setCollectionWayId(collectionReq.getCollectionWayId());
                useQuotaReq.setCollectionWayName(collectionReq.getCollectionWay());
                useQuotaReq.setCollectionTime(LocalDateTime.now());
//                    useQuotaReq.setCollectionVoucherJson(Lists.newArrayList(collectionReq.getCollectionCertificateJson()));
                useQuotaReq.setContactMobile(trainOrder.getContactMobile());

                BigDecimal exchangeRate = iMainDataCurrencyService.getExchangeRate(collectionReq.getCurrency(), CurrencyRateExchangeConstant.MARKET_EXCHANGE_RATE_);
                useQuotaReq.setExchangeRate(exchangeRate.doubleValue());

                useQuotaReq.setCurrencyId(collectionReq.getCurrencyId());
                useQuotaReq.setCurrencyName(Currency.getCurrencyById(collectionReq.getCurrencyId()).getCurrency());
                useQuotaReq.setUserId(user.getId());

                if(trainProductDTO != null){
                    useQuotaReq.setProductId(trainProductDTO.getId());
                    useQuotaReq.setProductName(Assist.join(trainOrder.getBoardingStationName(), " - ", trainOrder.getAlightingStationName()));
                    useQuotaReq.setProductNumber(trainProductDTO.getProductCode());
                    useQuotaReq.setSaleOrderId(trainOrder.getId());
                    useQuotaReq.setSaleOrderNumber(trainOrder.getOrderNumber());
                    useQuotaReq.setSaleUserId(trainOrder.getSalesmanId());
                    useQuotaReq.setSaleUserName(trainOrder.getSalesmanName());
                }
                useQuotaReqs.add(useQuotaReq);
            }
            if (Assist.isNotEmpty(useQuotaReqs)) {
                onAccountCurrencyQuotaService.useQuota(useQuotaReqs).ok();
            }
        }
    }

    /**
     * 校驗 掛賬額度是否夠用
     */
    private void checkQuotasMore(TrainOrderCollection collectionReq, TrainOrder trainOrder) {
        com.ctshk.rpc.finance.req.onaccount.QueryQuotaReq queryQuotaReq = new com.ctshk.rpc.finance.req.onaccount.QueryQuotaReq();
        queryQuotaReq.setCurrencyId(collectionReq.getCurrencyId());
        queryQuotaReq.setAccountId(trainOrder.getAgencyId());
        Result<com.ctshk.rpc.finance.dto.onaccount.QueryQuotaDTO> result = onAccountCurrencyQuotaService.queryQuota(queryQuotaReq);
        if(result.getCode() != 1){
            throw new BusinessException(SystemError.LOCAL_FUN_18008);
        }
        com.ctshk.rpc.finance.dto.onaccount.QueryQuotaDTO resultData = result.getData();
        if(resultData != null){
            if(resultData.getAvailableAmount().compareTo(collectionReq.getCollectionAmount()) < 0){
                throw new BusinessException(SystemError.LOCAL_FUN_18008);
            }
        }
    }

    /**
     * 根据币种ID获取汇率，获取汇率,
     *
     * @return
     */
    private MainDataCurrencyQueryDTO getExchangeRateById(Long currencyId) {
        MainDataCurrencyUpdateStatusReq mainDataCurrencyUpdateStatusReq = new MainDataCurrencyUpdateStatusReq();
        mainDataCurrencyUpdateStatusReq.setId(currencyId);
        Result<MainDataCurrencyQueryDTO> queryCurrencyRateResult = mainDataCurrencyService.query(mainDataCurrencyUpdateStatusReq);
        if (!queryCurrencyRateResult.isSuccess()) {
            SystemError defined = SystemError.getDefined(queryCurrencyRateResult.getCode());
            throw new BusinessException(defined);
        }
        return queryCurrencyRateResult.getData();
    }


    /**
     * 下单支付成功后，通知财务
     */
    private void addCollection(TrainOrder trainOrder, UserDTO userDTO, List<TrainOrderCollection> trainOrderCollectionList,
                               TrainProductDTO trainProductDTO, TokenUser user) {
        List<BillAddCollectionReq> billAddCollectionList = Lists.newArrayList();

        //存放产品id列表
        List<Long> productIds = Lists.newArrayList();
        productIds.add(trainOrder.getTrainId());

        //资源信息列表
        List<String> resourceInfoList = Lists.newArrayList();
        resourceInfoList.add(trainOrder.getDepartureCityName() + '-' + trainOrder.getArriveCityName());

        //获取航班信息
        trainOrderCollectionList.parallelStream().forEach(trainOrderCollection -> {
            BillAddCollectionReq billAddCollectionReq = new BillAddCollectionReq();
            //        单号
            billAddCollectionReq.setBillNumber(trainOrderCollection.getCollectionNumber());
            //        业务类型
            billAddCollectionReq.setBusinessType(SystemBusinessType.TRAIN_TICKET.getCode());
            //        收款方式ID
            billAddCollectionReq.setCollectionWayId(trainOrderCollection.getCollectionWayId());
            //        收款方式
            billAddCollectionReq.setCollectionWayName(trainOrderCollection.getCollectionWay());
            //        收款类型ID
            billAddCollectionReq.setCollectionTypeId(CollectionTypeIdCode.FULL.getCode());
            //        收款类型
            billAddCollectionReq.setCollectionTypeName(CollectionTypeIdCode.FULL.getMsg());
            //        收款金额
            billAddCollectionReq.setCollectionAmount(trainOrderCollection.getCollectionAmount());
            //        币种ID
            billAddCollectionReq.setCurrencyId(trainOrderCollection.getCurrencyId());
            //        币种名称
            billAddCollectionReq.setCurrencyName(trainOrderCollection.getCurrency());
            //       todo 待添加 汇率
            billAddCollectionReq.setExchangeRate(null);
            //        收款时间
            billAddCollectionReq.setCollectionTime(LocalDateTime.now());
            //        收款凭证JSON
            try { //避免出行json格式不对导致异常
                billAddCollectionReq.setCollectionVoucherJsonList(
                        JSONArray.parseArray(trainOrderCollection.getCollectionCertificateJson(), FileJson.class)
                );
            } catch (JSONException e) {
                e.printStackTrace();
            }
            //        销售单号
            billAddCollectionReq.setSaleOrderNumber(trainOrder.getOrderNumber());
            //        销售单ID
            billAddCollectionReq.setSaleOrderId(trainOrder.getId());
            //        产品ID
            billAddCollectionReq.setProductId(productIds);
            //        产品编号/团号
            billAddCollectionReq.setProductNumber(trainProductDTO.getProductCode());
            //       todo 产品名称
//            billAddCollectionReq.setProductName();
            //        资源信息
            billAddCollectionReq.setResourceInfo(resourceInfoList);
            //        销售人员ID
            billAddCollectionReq.setSaleUserId(user.getId());
            //        销售人员名称
            billAddCollectionReq.setSaleUserName(user.getNickname());
            //        销售部门ID
            billAddCollectionReq.setSaleDeptId(userDTO.getDeptId());
            //        用户ID
            billAddCollectionReq.setUserId(user.getId());
            billAddCollectionList.add(billAddCollectionReq);
        });
        Result result = iFinanceBillService.addCollection(billAddCollectionList);
        if (result.getCode() != 0) {
            throw new BusinessException(SystemError.AIR_ORDER_15015, result.getMsg());
        }
    }

    /**
     * 下单支付成功后，对接供应商
     */
    private void payOrderToSupplier(TokenUser user, TrainOrder trainOrder, TrainProductDTO trainProduct,
                                    List<TrainOrderTourist> touristList, UserDTO userDTO) {
        SupplierOrderSystemTrainAddReq callReq = new SupplierOrderSystemTrainAddReq();
        callReq.setSupplierId(trainProduct.getSupplierId());
        callReq.setSupplierName(trainProduct.getSupplierName());
        callReq.setSupplierOrderType("2");
        callReq.setBusinessType(SystemBusinessType.TRAIN_TICKET.getCode());
        callReq.setReserveTypeId(SupplierReserveTypeEnum.TRAIN.getId());
        callReq.setProductType(trainOrder.getProductType());
        callReq.setSaleNumber(trainOrder.getOrderNumber());
        callReq.setSaleType(SalesMethod.SINGLE_SALE.getCode());
        callReq.setProductNumber(trainProduct.getProductCode());
        callReq.setProductName(Assist.join(trainProduct.getBoardingStationName(), " - ", trainProduct.getAlightingStationName()));
        callReq.setTotalFee(trainOrder.getOrderAmount());
        if (userDTO != null) {
            callReq.setOriginalSaleNumber(Assist.toString(userDTO.getDeptId()));
            callReq.setDepartmentId(userDTO.getDeptId());
            callReq.setDepartment(userDTO.getDept());
        }

        LocalDate departureDate = trainOrder.getDepartureTime().toLocalDate();
        List<TrainProductCostPriceDTO> trainProductCostPriceDTOlist = trainProductCostService.queryDetailByTrainProductIdAndLocalDate(trainProduct.getId(), departureDate);
        Map<Long, TrainProductCostPriceDTO> costMap = trainProductCostPriceDTOlist.stream().collect(Collectors.toMap(TrainProductCostPriceDTO::getPassengerId, Function.identity()));
        if(!trainProductCostPriceDTOlist.isEmpty()) {
            TrainProductCostPriceDTO trainProductCostPriceDTO = trainProductCostPriceDTOlist.get(0);
            callReq.setCurrencyId(trainProductCostPriceDTO.getCurrencyId());
            callReq.setCurrency(trainProductCostPriceDTO.getCurrency());
        }

        callReq.setPayableAmount(trainOrder.getReceivableAmount());
        callReq.setConfirmStatus(trainOrder.getScheduledStatus());
        //获取当前用户信息
        UserDTO chargePersonUser = iSysUserService.queryCacheUser(trainProduct.getChargePersonId());
        callReq.setDepartmentId(chargePersonUser.getDeptId());
        callReq.setDepartment(chargePersonUser.getDept());
        List<SupplierSystemOrderTrainAddReq> orderCallReqList = new ArrayList<>();
        SupplierSystemOrderTrainAddReq orderCallReq = new SupplierSystemOrderTrainAddReq();
        orderCallReq.setOrderId(trainOrder.getId());
        // 适合人群
        orderCallReq.setSuitablePeople(trainProduct.getIntendedForName());
        List<SupplierSystemOrderTrainTicketAddReq> touristCallReqList = new ArrayList<>();
        Assist.forEach(touristList, tourist -> {
            SupplierSystemOrderTrainTicketAddReq touristCallReq = new SupplierSystemOrderTrainTicketAddReq();
            touristCallReq.setTrainId(null);
            touristCallReq.setOrderId(trainOrder.getId());
            touristCallReq.setGoLocationJson(Assist.buildJson("id", trainOrder.getDepartureCityId(), "name", trainOrder.getDepartureCityName()));
            touristCallReq.setDesLocationJson(Assist.buildJson("id", trainOrder.getArriveCityId(), "name", trainOrder.getArriveCityName()));
            touristCallReq.setTrainNumber(trainOrder.getTrainNumberName());
            touristCallReq.setStartTime(trainOrder.getDepartureTime());
            touristCallReq.setEndTime(null);
            touristCallReq.setTouristId(tourist.getId());
            touristCallReq.setTouristName(tourist.getTouristName());
            touristCallReq.setTouristTypeId(null);
            touristCallReq.setTouristType(tourist.getTouristType());
            //旅客类型
            Long touristTypeId = Assist.toLong(tourist.getTouristType());
            if (touristTypeId != null) {
                TrainProductCostPriceDTO busOrderCost = costMap.get(touristTypeId);
                if (busOrderCost != null) {
                    touristCallReq.setSinglePrice(busOrderCost.getPrice());
                }
            }
            touristCallReqList.add(touristCallReq);
        });
        orderCallReq.setSupplierSystemOrderTrainTicketAddReqList(touristCallReqList);
        orderCallReqList.add(orderCallReq);
        callReq.setSupplierSystemOrderTrainAddReqList(orderCallReqList);
        supplierOrderService.addSystemTrain(callReq, getTokenUserId(user)).ok();
    }

    /**
     * 取消订单
     *
     * @param cancelOrderReq
     * @param user
     */
    @Override
    public Result cancelOrder(TrainCancelOrderReq cancelOrderReq, TokenUser user) {
        TrainOrder trainOrder = baseMapper.selectById(cancelOrderReq.getOrderId());
        if (trainOrder == null) {
            throw new BusinessException(SystemError.TRAIN_PRODUCT_14020);
        }
        /*if (trainOrder.getPaymentStatus() == OrderPaymentStatus.ALREADY_PAYMENT.getCode() && trainOrder.getScheduledStatus() == OrderScheduledStatus.RESERVE_SUCCESS.getCode()) {
            // 已经付款，预订成功，不退不改
            throw new BusinessException(SystemError.TRAIN_PRODUCT_14021);
        }*/
        // 已经付款,预订失败才能取消订单
        LocalDateTime nowLocalDateTime = LocalDateTime.now();
        if (com.baomidou.mybatisplus.core.toolkit.CollectionUtils.isEmpty(cancelOrderReq.getTrainOrderRefundCancelReqList())) {
            // 退款记录不能为空
            throw new BusinessException(SystemError.TRAIN_PRODUCT_14022);
        }
        trainOrder.setCancelStatus(OrderCancelStatus.UNDER_APPROVAL.getCode());
        List<TrainOrderRefund> trainOrderRefundList = EntityUtil.copyList(cancelOrderReq.getTrainOrderRefundCancelReqList(), TrainOrderRefund.class);

        BigDecimal countRefundAmount = new BigDecimal(0);
        for (TrainOrderRefund trainOrderRefund : trainOrderRefundList) {
            // 获取对应汇率，计算支付金额
            if (trainOrderRefund.getCurrencyId() != null) {
                MainDataCurrencyQueryDTO currencyQueryDTO = getExchangeRateById(trainOrderRefund.getCurrencyId());
                BigDecimal marketExchangeRate = currencyQueryDTO.getMarketExchangeRate();
                BigDecimal refundAmountHKD = trainOrderRefund.getRefundAmount().multiply(marketExchangeRate);
                trainOrderRefund.setStandardAmount(refundAmountHKD);//本位币金额
                countRefundAmount = countRefundAmount.add(refundAmountHKD);
            }
            trainOrderRefund.setRefundNumber(OperateNumberGenerateUtil.generateRefundNumber(nowLocalDateTime));
            trainOrderRefund.setOrderId(cancelOrderReq.getOrderId());
            trainOrderRefund.setStatus(OrderRefundStatus.AUDITING.getCode());
            trainOrderRefund.setIsDeleted(IsDeletedCode.NO.getCode());
            trainOrderRefund.setCreateId(user.getId());
            trainOrderRefund.setRemark(cancelOrderReq.getRemark());
            trainOrderRefund.setGmtCreate(nowLocalDateTime);
            //trainOrderRefundMapper.insert(trainOrderRefund);
        }

        if (countRefundAmount.compareTo(trainOrder.getOrderAmount()) > 0) {
            // 退款金额不能大于付款金额
            throw new BusinessException(SystemError.TRAIN_PRODUCT_14033);
        }

        // 审批电子流
        Result<ApprovalStartDTO> approvalResult = sysApprovalService.start(SystemBusinessType.TRAIN_TICKET.getCode(), SysApprovalType.CANCEL_TRAIN.getCode(), cancelOrderReq.getOrderId(), user.getId(),null,null);
        if (!approvalResult.isSuccess()) {
            throw new BusinessException(SystemError.CUSTOM_ORDER_4044);
        }
        trainOrder.setRefundApprovalId(approvalResult.getData().getApprovalId());
        trainOrderRefundMapper.insertBatchSomeColumn(trainOrderRefundList);
        trainOrder.setModifiedId(user.getId());
        trainOrder.setGmtModified(nowLocalDateTime);
        baseMapper.updateById(trainOrder);
        return Result.success();
    }


    /**
     * 火车票线路列表
     *
     * @param req
     * @return
     */
    @Override
    public PageResponse<TrainOrderPageDTO> queyList(TrainOrderPageReq req, TokenUser user) {

        IPage<TrainOrderPageDTO> agentPage = new Page<>(req.getPageNo(), req.getPageSize());
        agentPage = baseMapper.queryList(req, agentPage);
        agentPage.getRecords().stream().forEach(trainOrderPageDTO -> {
            // 设置付款状态名称,预订状态名称,产品类型名称
            trainOrderPageDTO.setPaymentStatusName(OrderPaymentStatus.getOrderPaymentStatusName(trainOrderPageDTO.getPaymentStatus()));
            trainOrderPageDTO.setScheduledStatusName(OrderScheduledStatus.getOrderScheduledStatusName(trainOrderPageDTO.getScheduledStatus()));
            trainOrderPageDTO.setProductTypeName(ProductType.getProductTypeName(trainOrderPageDTO.getProductType()));
            trainOrderPageDTO.setSourceName(OrderSource.getOrderSourceName(trainOrderPageDTO.getSource()));
            if(OrderPaymentStatus.UN_PAYMENT.getCode() == trainOrderPageDTO.getPaymentStatus() && LocalDateTime.now().isAfter(trainOrderPageDTO.getPayExpireDate())) {
                trainOrderPageDTO.setIsExpire(1);
                trainOrderPageDTO.setPaymentStatusName(OrderPaymentStatus.ALREADY_CANCEL.getName());
            }

            // 销售人员名称
            UserDTO userDTO = sysUserService.queryCacheUser(trainOrderPageDTO.getCreateId());
            if (userDTO != null) {
                trainOrderPageDTO.setSalesmanName(String.format("%s/%s", userDTO.getFullName(), userDTO.getDept()));
            }

        });
        PageResponse<TrainOrderPageDTO> result = new PageResponse<>(agentPage.getRecords(), agentPage.getCurrent() == 1,
                agentPage.getTotal() <= (agentPage.getCurrent() * agentPage.getSize()),
                agentPage.getTotal(), agentPage.getCurrent(), agentPage.getSize());
        return result;
    }

    /**
     * 查询订单详情信息
     *
     * @param orderId 订单id
     * @return
     */
    @Override
    public Result<TrainOrderDetailDTO> queryOrderDetailInfo(Long orderId) {
        //根据订单id查询订单信息
        TrainOrder trainOrder = baseMapper.selectById(orderId);
        if (Objects.isNull(trainOrder)) {
            return Result.failed(SystemError.TRAIN_PRODUCT_14020);
        }
        TrainOrderDetailDTO trainOrderDetailDTO = EntityUtil.copy(trainOrder, TrainOrderDetailDTO.class);

        //订单状态
        if (trainOrderDetailDTO.getPaymentStatus() == null || OrderPaymentStatus.UN_PAYMENT.getCode().equals(trainOrderDetailDTO.getPaymentStatus())) {
            trainOrderDetailDTO.setOrderStatus(OrderStatus.UN_PAYMENT.getCode());
        } else if (trainOrderDetailDTO.getScheduledStatus() == null || OrderScheduledStatus.CONFIRM_RESERVE.getCode().equals(trainOrderDetailDTO.getScheduledStatus())) {
            trainOrderDetailDTO.setOrderStatus(OrderStatus.CONFIRM_RESERVE.getCode());
        } else if (OrderScheduledStatus.RESERVE_SUCCESS.getCode().equals(trainOrderDetailDTO.getScheduledStatus())) {
            trainOrderDetailDTO.setOrderStatus(OrderStatus.RESERVE_SUCCESS.getCode());
        } else if (OrderScheduledStatus.RESERVE_FAIL.getCode().equals(trainOrderDetailDTO.getScheduledStatus())) {
            trainOrderDetailDTO.setOrderStatus(OrderStatus.RESERVE_FAIL.getCode());
        }

        // 设置付款状态名称,预订状态名称,取消状态名称,产品类型名称,订单来源名称
        trainOrderDetailDTO.setPaymentStatusName(OrderPaymentStatus.getOrderPaymentStatusName(trainOrderDetailDTO.getPaymentStatus()));
        trainOrderDetailDTO.setScheduledStatusName(OrderScheduledStatus.getOrderScheduledStatusName(trainOrderDetailDTO.getScheduledStatus()));
        trainOrderDetailDTO.setCancelStatusName(OrderCancelStatus.getOrderCancelStatusName(trainOrderDetailDTO.getCancelStatus()));
        trainOrderDetailDTO.setProductTypeName(ProductType.getProductTypeName(trainOrderDetailDTO.getProductType()));
        trainOrderDetailDTO.setSourceName(OrderSource.getOrderSourceName(trainOrderDetailDTO.getSource()));


        //火车票外挂单
        TrainManualOrder trainManualOrder = trainManualOrderMapper.selectOne(new QueryWrapper<TrainManualOrder>().lambda().eq(TrainManualOrder::getOrderId, orderId));
        if (!Objects.isNull(trainManualOrder)) {
            TrainManualOrderDTO trainManualOrderDTO = EntityUtil.copy(trainManualOrder, TrainManualOrderDTO.class);
            trainOrderDetailDTO.setTrainManualOrderDTO(trainManualOrderDTO);
        }

        //火车票订单旅客信息
        List<TrainOrderTourist> trainOrderTouristList = trainOrderTouristMapper.selectList(new QueryWrapper<TrainOrderTourist>().lambda().eq(TrainOrderTourist::getOrderId, orderId));
        if (!CollectionUtils.isEmpty(trainOrderTouristList)) {
            List<TrainOrderTouristDTO> trainOrderTouristDTOList = EntityUtil.copyList(trainOrderTouristList, TrainOrderTouristDTO.class);
            trainOrderDetailDTO.setTrainOrderTouristDTOList(trainOrderTouristDTOList);
        }

        //火车票收款明细信息
        List<TrainOrderCollection> trainOrderCollectionList = trainOrderCollectionMapper.selectList(new QueryWrapper<TrainOrderCollection>().lambda().eq(TrainOrderCollection::getOrderId, orderId));
        if (!CollectionUtils.isEmpty(trainOrderCollectionList)) {
            List<TrainOrderCollectionDTO> trainOrderCollectionDTOList = EntityUtil.copyList(trainOrderCollectionList, TrainOrderCollectionDTO.class);
            trainOrderDetailDTO.setTrainOrderCollectionDTOList(trainOrderCollectionDTOList);
        }

        //火车票退款明细信息
        BigDecimal refundAmountCount = new BigDecimal(0);
        List<TrainOrderRefund> trainOrderRefundList = trainOrderRefundMapper.selectList(new QueryWrapper<TrainOrderRefund>().lambda().eq(TrainOrderRefund::getOrderId, orderId));
        if(!CollectionUtils.isEmpty(trainOrderRefundList)){
            List<TrainOrderRefundDTO> trainOrderRefundDTOList =  EntityUtil.copyList(trainOrderRefundList,TrainOrderRefundDTO.class);
            trainOrderDetailDTO.setTrainOrderRefundDTOList(trainOrderRefundDTOList);
            for (TrainOrderRefundDTO refundDTO : trainOrderDetailDTO.getTrainOrderRefundDTOList()) {
                UserDTO userDTO = sysUserService.queryCacheUser(refundDTO.getCreateId());
                if (userDTO != null) {
                    refundDTO.setApprovalUser(String.format("%s/%s", userDTO.getFullName(), userDTO.getDept()));
                }

                // 计算已退款, 或者正在退款的金额
                if (!refundDTO.getStatus().equals(OrderCancelStatus.APPROVAL_FAIL.getCode())) {
                    refundAmountCount = refundAmountCount.add(refundDTO.getRefundAmount());
                }
            }
        }

        // 设置有效金额
        if (refundAmountCount.compareTo(trainOrder.getReceivableAmount()) > 0) {
            trainOrderDetailDTO.setEffectiveAmount(new BigDecimal(0));
        } else {
            trainOrderDetailDTO.setEffectiveAmount(trainOrder.getReceivableAmount().subtract(refundAmountCount));
        }


        //火车信息
        if (trainOrder.getTrainId() != null) {
            TrainProductDTO busProductDTO = trainProductService.queryDetail(trainOrder.getTrainId());
            TrainProductReservationSettingsDTO trainProductReservationSettingsDTO = busProductDTO.getTrainProductReservationSettingsDTO();
            if (trainProductReservationSettingsDTO != null) {
                trainOrderDetailDTO.setBookingInformation(trainProductReservationSettingsDTO.getBookingInformation());
                trainOrderDetailDTO.setTicketCollectionType(trainProductReservationSettingsDTO.getTicketCollectionType());
                trainOrderDetailDTO.setExchangeMethod(trainProductReservationSettingsDTO.getExchangeMethod());
                trainOrderDetailDTO.setRefundFeeType(trainProductReservationSettingsDTO.getRefundFeeType());
                trainOrderDetailDTO.setRefundFeePrice(trainProductReservationSettingsDTO.getRefundFeePrice());
            }
        }
        return Result.success(trainOrderDetailDTO);
    }

    /**
     * 修改旅客信息
     */
    @Transactional(rollbackFor = Exception.class)
    @Override
    public Result updateBusOrderTourist(TrainOrderTouristReq touristReq, Long userId) {
        TrainOrderTourist trainOrderTourist = trainOrderTouristMapper.selectById(touristReq.getId());
        if (Objects.isNull(trainOrderTourist)) {
            return Result.failed(SystemError.BUS_ORDER_9006);
        }
        trainOrderTourist = EntityUtil.copy(touristReq, TrainOrderTourist.class);
        trainOrderTourist.setModifiedId(userId);
        trainOrderTourist.setGmtModified(LocalDateTime.now());
        trainOrderTouristMapper.updateById(trainOrderTourist);
        return Result.success();
    }


    @Transactional(rollbackFor = Exception.class)
    @Override
    public Result confirmRefund(Long id, Long refundId, Long userId) {
        TrainOrder trainOrder = baseMapper.selectById(id);
        if (trainOrder == null) {
            //订单不存在
            throw new BusinessException(SystemError.TRAIN_PRODUCT_14020);
        }
        if (!(trainOrder.getCancelStatus() == OrderCancelStatus.APPROVAL_SUCCESS.getCode())) {
            //审批成功状态的订单，才可以做确认退款操作
            throw new BusinessException(SystemError.TRAIN_PRODUCT_14024);
        }
        QueryWrapper<TrainOrderRefund> busOrderRefundQueryWrapper = new QueryWrapper<>();
        busOrderRefundQueryWrapper.lambda().eq(TrainOrderRefund::getOrderId, id);
        List<TrainOrderRefund> trainOrderRefundList = trainOrderRefundMapper.selectList(busOrderRefundQueryWrapper);
        boolean ifAllRefund = true;
        for (TrainOrderRefund trainOrderRefund : trainOrderRefundList) {
            if(refundId == null) {
                // 确认退款
                trainOrderRefund.setStatus(OrderRefundStatus.REFUND_SUCCESSFUL.getCode());
                trainOrderRefundMapper.updateById(trainOrderRefund);
            } else if (refundId.equals(trainOrderRefund.getId())) {
                // 确认退款
                trainOrderRefund.setStatus(OrderRefundStatus.REFUND_SUCCESSFUL.getCode());
                trainOrderRefundMapper.updateById(trainOrderRefund);
            }
            /**
             * do something暂无支付方式主数据，5-银行优惠，会员积分，优惠券，
             * 除5以外的支付方式记录的状态，有一个不是退款成功，ifAllRefund为false
             */
            if (!(trainOrderRefund.getRefundWayId() == 5) && !(trainOrderRefund.getStatus() == OrderRefundStatus.REFUND_SUCCESSFUL.getCode())) {
                ifAllRefund = false;
            }
        }
        if (ifAllRefund) {
            // 全部已退款,更新状态
            trainOrder.setCancelStatus(OrderCancelStatus.ALREADY_REFUND.getCode());
            baseMapper.updateById(trainOrder);
        }
        return Result.success();
    }

    @Override
    public Result confirmRefund(Long id, Long userId) {
        Result<TrainOrderDetailDTO> list = queryOrderDetailInfo(id);
        list.getData().getTrainOrderRefundDTOList();
        return confirmRefund(id, null, userId);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Result refundApproval(TrainOrderRefundApprovalReq req, TokenUser tokenUser) {
        //通过审批id查找对应订单信息
        TrainOrder order = baseMapper.selectOne(
                Wrappers.<TrainOrder>lambdaQuery()
                        .eq(TrainOrder::getRefundApprovalId, req.getApprovalId()));
        if (Objects.isNull(order))
            throw new BusinessException(SystemError.TRAIN_PRODUCT_14020);
        //校验审批状态是否正确
        ApprovalStatus approvalStatus = ApprovalStatus.getDefined(req.getApprovalStatus());
        if(Objects.isNull(approvalStatus))
            throw new BusinessException(SystemError.WORKFLOW_APPROVAL_7012);
        //调用审批系统接口
        Result<ApprovalCheckDTO> approvalResult = sysApprovalService.check(
                req.getApprovalId(),
                tokenUser.getId(),
                approvalStatus.getCode(),
                req.getComments());
        if(!approvalResult.isSuccess())
            throw new BusinessException(SystemError.getDefined(approvalResult.getCode()));
        //如果是审批通过并且审批流畅未结束则直接返回
        if (ApprovalStatus.REVIEW_YES.equals(approvalStatus) && !approvalResult.getData().getIsFinish()) {
            return Result.success();
        }

        // 更新审批金额
        List<TrainOrderRefund> orderRefunds = EntityUtil.copyList(req.getOrderRefundApprovalRecordReqList(), TrainOrderRefund.class);
        BigDecimal refundedAmountCount = new BigDecimal(0);
        for (TrainOrderRefund trainOrderRefund : orderRefunds) {
            refundedAmountCount = refundedAmountCount.add(trainOrderRefund.getApprovalAmount());
            trainOrderRefundMapper.updateById(trainOrderRefund);
        }
        if (refundedAmountCount.compareTo(order.getReceivableAmount()) > 0) {
            // 退款金额不能大于实付金额
            throw new BusinessException(SystemError.TRAIN_PRODUCT_14033);
        }

        //改变订单状态, 退款审批成功更新退款金额
        TrainOrder updateOrder = new TrainOrder();
        updateOrder.setId(order.getId());
        updateOrder.setCancelStatus(
                ApprovalStatus.REVIEW_YES.equals(approvalStatus) ?
                        OrderCancelStatus.APPROVAL_SUCCESS.getCode() :
                        OrderCancelStatus.APPROVAL_FAIL.getCode()
        );
        updateOrder.setRefundedAmount(ApprovalStatus.REVIEW_YES.equals(approvalStatus) ? refundedAmountCount : null);
        baseMapper.updateById(updateOrder);

        //改变订单退款明细状态
        trainOrderRefundMapper.update(null,
                Wrappers.<TrainOrderRefund>lambdaUpdate().set(TrainOrderRefund::getStatus,
                        ApprovalStatus.REVIEW_YES.equals(approvalStatus) ?
                                OrderRefundStatus.AUDIT_SUCCESSFUL.getCode()
                                : OrderRefundStatus.AUDIT_FAILED.getCode())
                        .eq(TrainOrderRefund::getOrderId, order.getId()));
        //如果是审批通过则需要通知财务系统
        if (ApprovalStatus.REVIEW_YES.equals(approvalStatus)) {
            refundNotificationFinance(tokenUser, order);
        }
        return Result.success();
    }

    @Transactional
    @Override
    public Result TrainOrder(TrainOrderConfirmReq req, TokenUser tokenUser) {
        // 火车产品预定设置为二次确认或者外挂单出票方式为後臺產品出票才能调用供应商确认预订
        boolean needFreeCallSystemConfirm = false;
        TrainOrder trainOrder = trainOrderMapper.selectById(req.getId());
        TrainProductDTO trainProductDTO = trainProductService.queryDetail(trainOrder.getTrainId());
        if(trainOrder.getOrderType() == 1) {
            QueryWrapper<TrainManualOrder> queryWrapper = new QueryWrapper();
            queryWrapper.lambda().eq(TrainManualOrder::getOrderId, trainOrder.getId());
            // 查询外挂单
            TrainManualOrder trainManualOrder = trainManualOrderMapper.selectOne(queryWrapper);
            // 查询出票方式 后台出票需要调用供应商确认预定
            if(trainManualOrder.getTicketMode() == 2) {
                needFreeCallSystemConfirm = true;
            }
        } else {
            TrainProductReservationSettingsDTO trainProductReservationSettingsDTO = trainProductDTO.getTrainProductReservationSettingsDTO();
            Integer isConfirm = trainProductReservationSettingsDTO.getIsConfirm();
            if(isConfirm == 1) {
                // 火车产品预定设置为二次确认
                needFreeCallSystemConfirm = true;
            }
        }

        //是否需要调用供应商接口
        if(needFreeCallSystemConfirm) {
            //订单更新为预定成功
            TrainRefreshByConfirmOrderReq trainRefreshByConfirmOrderReq = new TrainRefreshByConfirmOrderReq();
            trainRefreshByConfirmOrderReq.setId(req.getId());
            trainRefreshByConfirmOrderReq.setScheduledStatus(OrderScheduledStatus.RESERVE_SUCCESS.getCode());
            refreshByConfirmOrder(trainRefreshByConfirmOrderReq, tokenUser).ok();

            //调用供应商接口
            SupplierOrderSystemFreeCallConfirmReq callReq = toBean(req, SupplierOrderSystemFreeCallConfirmReq.class);
            supplierOrderService.freeCallSystemConfirm(callReq, getTokenUserId(tokenUser)).ok();
            return Result.success();
        } else {
            return Result.failed(new BusinessException(SystemError.TRAIN_ORDER_24000,"不符合确认订单条件"));
        }
    }

    /**
     * 确认订单后的相关火车处理
     * @param req
     * @return
     */
    @Transactional
    @Override
    public Result refreshByConfirmOrder(TrainRefreshByConfirmOrderReq req, TokenUser tokenUser) {
        validateArgs(req);

        TrainOrder entity = newUpdateEntity(TrainOrder.class, req, tokenUser);
        trainOrderMapper.assertUpdateById(entity);

        return Result.success();
    }

    @Override
    public List<OrderRefundDTO> getRefundList(String orderNumber) {
        TrainOrder trainOrder = baseMapper.selectOne(Wrappers.<TrainOrder>lambdaQuery()
                .eq(TrainOrder::getIsDeleted, IsDeletedCode.NO)
                .eq(TrainOrder::getOrderNumber, orderNumber));
        if (trainOrder == null) {
            //订单不存在
            throw new BusinessException(SystemError.AIREXPRESS_ORDER_60002);
        }
        List<OrderRefundDTO> orderRefundDTOList = new ArrayList<>();
        List<TrainOrderCollection> trainOrderCollections = trainOrderCollectionMapper.selectList(Wrappers.<TrainOrderCollection>lambdaQuery()
                .eq(TrainOrderCollection::getIsDeleted, IsDeletedCode.NO)
                .eq(TrainOrderCollection::getOrderId, trainOrder.getId()));
        List<TrainOrderRefund> trainOrderRefunds = trainOrderRefundMapper.selectList(Wrappers.<TrainOrderRefund>lambdaQuery()
                .eq(TrainOrderRefund::getIsDeleted, IsDeletedCode.NO)
                .eq(TrainOrderRefund::getOrderId, trainOrder.getId()));
        if(com.baomidou.mybatisplus.core.toolkit.CollectionUtils.isEmpty(trainOrderRefunds)){
            return orderRefundDTOList;
        }
        BigDecimal alreadyAmount = BigDecimal.ZERO;
        for (TrainOrderCollection trainOrderCollection : trainOrderCollections) {
            alreadyAmount = alreadyAmount.add(trainOrderCollection.getStandardAmount());
        }
        for (TrainOrderRefund orderRefund : trainOrderRefunds) {
            OrderRefundDTO orderRefundDTO = new OrderRefundDTO();
            orderRefundDTO.setBusinessType(SystemBusinessType.TRAIN_TICKET.getCode());
            orderRefundDTO.setRefundId(trainOrder.getId());
            orderRefundDTO.setRefundNumber(trainOrder.getOrderNumber());
            orderRefundDTO.setRefundReason(orderRefund.getRefundReason());
            orderRefundDTO.setRemark(orderRefund.getRemark());
            orderRefundDTO.setRefundType(orderRefund.getRefundWay());
            orderRefundDTO.setTotalReceivables(trainOrder.getReceivableAmount());
            orderRefundDTO.setPaidInAmount(alreadyAmount);
            orderRefundDTO.setRefundAmount(orderRefund.getRefundAmount());
            orderRefundDTO.setApprovalAmount(orderRefund.getRefundAmount()); //允许退款金额
            orderRefundDTO.setCurrency(orderRefund.getCurrency());
            orderRefundDTOList.add(orderRefundDTO);
        }
        return orderRefundDTOList;
    }

    @Override
    public Result<Void> supplieConfirmOrder(TrainOrderSupplieConfirmReq req, Long userId) {
        validateArgs(req);

        TrainOrder entity = trainOrderMapper.assertExistSelectOneByKey("order_number", req.getSaleNumber());
        fillUpdateEntityUserId(entity, userId);
        entity.setScheduledStatus(req.getReserveStatus());

        trainOrderMapper.assertUpdateById(entity);

        return newResult();
    }

    @Override
    public Result sendMessageToTourist(TrainOrderSendMessageToTouristReq sendMessageToTouristReq) {
        InformPassengersWay instance = InformPassengersWay.getInstance(sendMessageToTouristReq.getInformPassengersWay());
        if (Objects.isNull(instance))
            return Result.failed(SystemError.AIR_ORDER_15014);
        switch (instance) {
            case SMS:
                HashMap<String, String> paramMap = new HashMap<>();
                paramMap.put("namevotes", "");
                paramMap.put("use", sendMessageToTouristReq.getMessage());
                paramMap.put("service", "(852)2998 7888");
                try {
                    SmsUtil.sendSms(sendMessageToTouristReq.getAreaCode() + sendMessageToTouristReq.getNumber(), "SMS_215980892", paramMap);
                } catch (Exception e) {
                    log.error("【火车票订单收据】发送短信失败,error:{}", e);
                    throw new BusinessException(SystemError.AIREXPRESS_ORDER_60037, e.getMessage());
                }
                return Result.success();
            case EMAIL:
                mailTemplate.sendSimpleMail(sendMessageToTouristReq.getNumber(),
                        "訂單確認通知", sendMessageToTouristReq.getMessage());
                return Result.success();
            default:
                throw new BusinessException(SystemError.AIR_ORDER_15014);
        }
    }

    @Override
    public Result<List<TrainOrderDetailDTO>> recentToNow(LocalDateTime recent, LocalDateTime now) {
        List<TrainOrder> orderList = baseMapper.selectList(Wrappers.<TrainOrder>lambdaQuery()
                .eq(TrainOrder::getIsDeleted,IsDeletedCode.NO.getCode())
                .ge(recent != null,TrainOrder::getGmtModified, recent)
                .le(TrainOrder::getGmtModified, now));
        return Result.success(EntityUtil.copyList(orderList, TrainOrderDetailDTO.class));
    }

    @Override
    public List<TrainOrderDTO> queryOrderDTOList(LocalDateTime start, LocalDateTime end) {
        return EntityUtil.copyList(baseMapper.selectList(Wrappers.<TrainOrder>lambdaQuery()
                .eq(TrainOrder::getIsDeleted, IsDeletedCode.NO.getCode())
                .ge(TrainOrder::getGmtCreate, start)
                .le(TrainOrder::getGmtCreate, end)),TrainOrderDTO.class);
    }

    @Override
    public Integer findBusProduct7DaySaleCount(Long id) {
        return baseMapper.selectSaleCount(id);
    }

    /**
     * 退款审核通过通知财务
     * @param tokenUser
     * @param order
     */
    private void refundNotificationFinance(TokenUser tokenUser, TrainOrder order) {
        List<TrainOrderRefund> trainOrderRefundList = trainOrderRefundMapper.selectList(
                Wrappers.<TrainOrderRefund>lambdaQuery().eq(TrainOrderRefund::getOrderId, order.getId()));
        //获取收款信息
        List<TrainOrderCollection> orderCollectionList = trainOrderCollectionMapper.selectList(Wrappers.<TrainOrderCollection>lambdaQuery()
                .eq(TrainOrderCollection::getOrderId, order.getId()));
        //火车产品信息
        TrainProductDTO trainProductDTO = trainProductService.queryDetail(order.getTrainId());
        //旅客信息
        List<BillAddRefundReq> billAddRefundList = Lists.newArrayList();
        //组装财务系统需要数据
        trainOrderRefundList.stream().forEach(item -> {
            BillAddRefundReq billAddRefundReq = new BillAddRefundReq();
            billAddRefundReq.setBillNumber(item.getRefundNumber());
            billAddRefundReq.setBusinessType(SystemBusinessType.TRAIN_TICKET.getCode());
            billAddRefundReq.setCollectionAmount(item.getRefundAmount());
            billAddRefundReq.setCurrencyId(item.getCurrencyId());
            billAddRefundReq.setCurrencyName(item.getCurrency());
            BigDecimal exchangeRate = mainDataCurrencyService.getExchangeRate(item.getCurrency(), CurrencyRateExchangeConstant.PLANNED_EXCHANGE_RATE_);
            billAddRefundReq.setExchangeRate(exchangeRate.doubleValue());
            billAddRefundReq.setSaleOrderNumber(order.getOrderNumber());
            billAddRefundReq.setSaleOrderId(order.getId());
            billAddRefundReq.setProductId(Lists.newArrayList(trainProductDTO.getId()));
            billAddRefundReq.setResourceInfo(Lists.newArrayList(trainProductDTO.getDepartureCityName() + "-" + trainProductDTO.getArriveCityName()));
            billAddRefundReq.setSaleUserId(order.getSalesmanId());
            billAddRefundReq.setSaleUserName(order.getSalesmanName());
            billAddRefundReq.setRefundTypeId(item.getRefundWayId());
            billAddRefundReq.setRefundType(item.getRefundWay());
            billAddRefundReq.setRefundAccountJson(new AccountJson().setCardNumber(item.getRefundAccount()));
            billAddRefundReq.setContactMobile(order.getContactMobile());
            billAddRefundReq.setRefundTime(item.getGmtCreate());
            billAddRefundReq.setPayVoucherJson(orderCollectionList.stream()
                    .map(airOrderCollection -> JSON.parseObject(airOrderCollection.getCollectionCertificateJson(), FileJson.class))
                    .collect(Collectors.toList()));
            billAddRefundReq.setRefundRemark(item.getRemark());
            billAddRefundReq.setUserId(tokenUser.getId());
            billAddRefundList.add(billAddRefundReq);
        });
        Result result = iFinanceBillService.addRefund(billAddRefundList);
        if (!result.isSuccess()) {
            throw new BusinessException(SystemError.getDefined(result.getCode()));
        }
    }

    /**
     * 根据总价计算应收价格，减去会员积分和优惠券
     *
     * @param trainOrder
     * @param orderAmount
     */
    private void buildReceivableAmount(TrainOrder trainOrder, BigDecimal orderAmount) {
        BigDecimal receivableAmount = new BigDecimal(orderAmount.toString());
        //计算应收价格-是否使用积分
        if (trainOrder.getUsingPoints() != null) {
            BigDecimal usingPoints = new BigDecimal(String.valueOf(trainOrder.getUsingPoints()));
            // 校验会员积分是否充足
            checkMemberPoints(trainOrder, usingPoints);
            //计算应收价格-计算积分
            BigDecimal usingPointsCNY = usingPoints.divide(new BigDecimal("100"), 2, BigDecimal.ROUND_HALF_UP);
            //人民币兑港币
            BigDecimal crmExchangeRate = getCrmExchangeRateByName(Currency.CNY.getSymbol());
            BigDecimal usingPointsHKD = usingPointsCNY.multiply(crmExchangeRate);
            if (receivableAmount.compareTo(usingPointsHKD) < 0) {
                // 总价减去积分价后为负数，不予许提交
                throw new BusinessException(SystemError.AIREXPRESS_ORDER_60007);
            }
            receivableAmount = receivableAmount.subtract(usingPointsHKD);
        }
        //计算应收价格-计算推广码（优惠券）
        if (trainOrder.getCouponId() != null) {
            // do something 推广码接口未写完，等待中
//            OperatePromotionQueryReq operatePromotionQueryReq = new OperatePromotionQueryReq();
//            operatePromotionQueryReq.setId(airportExpressOrder.getCouponId());
//            Result<OperatePromotionQueryDTO> operatePromotionQueryDTOResult = operatePromotionService.query(operatePromotionQueryReq);
        }
        trainOrder.setReceivableAmount(receivableAmount);
    }


    /**
     * 银行优惠工具类
     */
    private BigDecimal getAmountByBankReference(TrainOrder busOrder, Long unionpayDiscountId) {
        OperateBankConformQueryReq operateBankConformQueryReq = new OperateBankConformQueryReq();
        operateBankConformQueryReq.setId(unionpayDiscountId);
        Result<OperateBankPreferenceQueryDTO> operateBankPreferenceQueryDTOResult = operateBankPreferenceService.queryConform(operateBankConformQueryReq);
        if (!operateBankPreferenceQueryDTOResult.isSuccess()) {
            // 校验银行优惠不满足条件
            throw new BusinessException(SystemError.AIREXPRESS_ORDER_60018);
        }
        OperateBankPreferenceQueryDTO bankQueryDto = operateBankPreferenceQueryDTOResult.getData();
        if (bankQueryDto.getDiscountType() == 1) {
            // 校验应收价格是否符合满减优惠
            if (busOrder.getReceivableAmount().compareTo(bankQueryDto.getFullAmount()) >= 0) {
                return bankQueryDto.getReductionAmount();
            } else {
                // 校验银行优惠不满足条件
                throw new BusinessException(SystemError.AIREXPRESS_ORDER_60018);
            }
        } else {
            // 使用百分比优惠
            BigDecimal currentAmount = busOrder.getReceivableAmount().multiply(new BigDecimal(String.valueOf(bankQueryDto.getDiscountPercent())));
            return currentAmount.compareTo(bankQueryDto.getMaxDiscount()) > 0 ? bankQueryDto.getMaxDiscount() : currentAmount;
        }
    }

    /**
     * 校验积分是否充足
     *
     * @param busOrder
     * @param usingPoints
     */
    private void checkMemberPoints(TrainOrder busOrder, BigDecimal usingPoints) {
        ContactQueryDTO contactQuery;
        try {
            CrmMemberQueryReq crmMemberQueryReq = new CrmMemberQueryReq(1, busOrder.getMemberId(), null);
            contactQuery = crmMemberService.queryMember(crmMemberQueryReq);
        } catch (Exception e) {
            if (e instanceof BusinessException) {
                throw e;
            } else {
                throw new BusinessException(SystemError.AIREXPRESS_ORDER_60009);
            }
        }
        BigDecimal findMemberPoints = new BigDecimal(String.valueOf(contactQuery.getMember().getPoint1Value()));
        if (findMemberPoints.compareTo(usingPoints) < 0) {
            // 会员积分不足
            throw new BusinessException(SystemError.AIREXPRESS_ORDER_60008);
        }
    }


    /**
     * 根据币种名称获取汇率
     *
     * @param currencySy
     * @return
     */
    private BigDecimal getCrmExchangeRateByName(String currencySy) {
        MainDataCurrencyListReq mainDataCurrencyListReq = new MainDataCurrencyListReq();
        mainDataCurrencyListReq.setName(currencySy);
        PageResponse<MainDataCurrencyListDTO> list = iMainDataCurrencyService.list(mainDataCurrencyListReq);
        if (com.baomidou.mybatisplus.core.toolkit.CollectionUtils.isEmpty(list.getRecords())) {
            throw new BusinessException(SystemError.AIREXPRESS_ORDER_60003);
        }
        return list.getRecords().get(0).getCrmExchangeRate();
    }

    /**
     * 生成火车票销售编号=PG+部门代码+员工编号+年后2位+月日4位+3位随机数字
     *
     * @param userId
     * @return
     */
    private String buildOrderNumber(Long userId, LocalDateTime nowLocalDateTime) {
        UserDTO userDTO = sysUserService.loadUserByParam(userId, 1);
        String employeeNumber = userDTO.getEmployeeNumber();
        SysDepartmentDTO sysDepartmentDTO = sysDepartmentService.queryOne(userDTO.getDeptId());
        String deptCode = sysDepartmentDTO.getDeptCode();
        String yearCode = String.valueOf(nowLocalDateTime.getYear()).substring(2, 4);
        String monthCode = StringUtils.leftPad(String.valueOf(nowLocalDateTime.getMonthValue()), 2, "0");
        String dayCode = StringUtils.leftPad(String.valueOf(nowLocalDateTime.getDayOfMonth()), 2, "0");
        String randomNumber = String.valueOf((int) ((Math.random() * 9 + 1) * 100));
        StringBuilder orderNumberSb = new StringBuilder();
        orderNumberSb.append("G").append(deptCode).append(employeeNumber).append(yearCode).append(monthCode).append(dayCode).append(randomNumber);
        return orderNumberSb.toString();
    }
}
